package com.ray.test.proxy;

import com.alibaba.fastjson.JSON;
import com.ray.test.config.DefaultMothedConfig;
import com.ray.test.util.AopTargetUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.aop.support.AopUtils;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
import org.springframework.context.ApplicationContext;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.util.Map;

/**
 * @author bo shen
 * @Description: cjlib代理
 * @Class: MethodHander
 * @Package com.ray.test.proxy
 * @date 2019/12/18 10:25
 * @company <p>杭州传化陆鲸科技有限公司</p>
 * @updateRecord time(修改时间)  author(修改人)   desc(修改内容)
 */
@Slf4j
public class MockMethodHander implements MethodInterceptor, InvocationHandler {

    /***spring容器**/
    private ApplicationContext applicationContext;

    private Object target;



    public MockMethodHander(ApplicationContext applicationContext, Object target) {
        this.applicationContext = applicationContext;
        this.target = target;
    }

    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        return doAll(o, method, objects);
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        return doAll(proxy, method, args);
    }


    private Object doAll(Object proxy, Method method, Object[] args) throws Throwable {
        //默认方法不用执行
        if (DefaultMothedConfig.isClassMethod(method.getName())) {
            return method.invoke(target, args);
        }
        MockTestConfig config = MockTestConfig.get();
        Class clazz = AopTargetUtils.getTargetClass(proxy);
        MethodResult methodResult = new MethodResult(clazz, method.getName(), config.integer.getAndIncrement(), null);
        Map<String, MethodResult> map = config.getMockData().getResults();
        log.info("{}方法被调用,配置信息:{}", method.getName(), JSON.toJSONString(config));
        // log.info("{}方法被结果数据:{}", method.getName(),JSON.toJSONString(map));
        Object result = null;
        if (config != null && config.isMock() && config.isHasData()) {
            log.info("key:{}", methodResult.getKey());
            result = map.get(methodResult.getKey()).getResult();
        } else {
            try {
                result = method.invoke(target, args);
                methodResult.setResult(result);
                config.getMockData().getResults().put(methodResult.getKey(), methodResult);
            } catch (Exception e) {
                log.info("调用服务异常", e);
                throw new RuntimeException("调用服务异常");
            }
        }
        log.info("{}方法被调用结果:{}", method.getName(), JSON.toJSONString(result));
        return result;
    }

}
